import Router from 'koa-router';
import { pool } from '../../config/database';
import { authMiddleware } from '../../middleware/auth';
import { RowDataPacket, ResultSetHeader } from 'mysql2';
import { ApiResponse } from '../../types';
import axios from 'axios';
import jwt from 'jsonwebtoken';
import { config } from '../../config/env';
import crypto from 'crypto';

const router = new Router({ prefix: '/api/amap/ip' });

// IP定位接口类型定义
interface AmapIpResponse {
  status: string;
  info: string;
  infocode: string;
  province?: string;
  city?: string;
  adcode?: string;
  rectangle?: string;
}

interface IpLocationData {
  ip: string;
  province?: string;
  city?: string;
  adcode?: string;
  rectangle?: string;
  response_time: Date;
}

// 获取真实公网IP
async function getRealPublicIP(): Promise<string> {
  try {
    console.log('🌍 正在获取真实公网IP...');
    const response = await axios.get('https://ipinfo.io/ip', {
      timeout: 5000,
      headers: {
        'User-Agent': 'xlCig-LocationService/1.0'
      }
    });
    const publicIP = response.data.trim();
    console.log(`✅ 获取到真实公网IP: ${publicIP}`);
    return publicIP;
  } catch (error) {
    console.error('❌ 获取公网IP失败，使用备用方法:', error);
    // 备用方法：使用其他服务
    try {
      const backupResponse = await axios.get('https://api.ipify.org?format=text', {
        timeout: 3000
      });
      return backupResponse.data.trim();
    } catch (backupError) {
      console.error('❌ 备用IP获取也失败:', backupError);
      throw new Error('无法获取真实公网IP');
    }
  }
}
export { getRealPublicIP };

// 获取客户端真实IP
function getClientIP(ctx: any): string {
  // 1. 优先使用 X-Forwarded-For 头部（nginx代理设置）
  const forwarded = ctx.request.headers['x-forwarded-for'];
  if (forwarded) {
    // X-Forwarded-For 可能包含多个IP，取第一个（最原始的客户端IP）
    const forwardedIps = forwarded.toString().split(',').map((ip: string) => ip.trim());
    const clientIp = forwardedIps[0];
    if (clientIp && clientIp !== 'unknown') {
      console.log(`📍 从X-Forwarded-For获取客户端IP: ${clientIp}`);
      return clientIp;
    }
  }
  
  // 2. 使用 X-Real-IP 头部（nginx代理设置）
  const realIp = ctx.request.headers['x-real-ip'];
  if (realIp && realIp.toString() !== 'unknown') {
    console.log(`📍 从X-Real-IP获取客户端IP: ${realIp}`);
    return realIp.toString();
  }
  
  // 3. 使用 Koa 的内置 IP 获取
  const koaIp = ctx.request.ip || ctx.ip;
  if (koaIp) {
    console.log(`📍 从Koa内置方法获取IP: ${koaIp}`);
    return koaIp;
  }
  
  // 4. 备用：从连接信息获取
  const remoteAddress = ctx.request.socket?.remoteAddress;
  if (remoteAddress) {
    console.log(`📍 从socket连接获取IP: ${remoteAddress}`);
    return remoteAddress;
  }
  
  console.log(`⚠️ 无法获取客户端IP，使用默认值`);
  return '127.0.0.1';
}

// 检查用户是否已登录
function checkUserAuth(ctx: any): any {
  try {
    const token = ctx.headers.authorization?.replace('Bearer ', '');
    if (!token) {
      return null;
    }
    
    const decoded = jwt.verify(token, config.jwt.secret);
    return decoded;
  } catch (error) {
    return null;
  }
}

// 更新用户登录IP和定位信息
async function updateUserLocationInfo(userId: number, ip: string, province?: string, city?: string): Promise<void> {
  try {
    const updateFields = ['loginIp = ?'];
    const updateValues: (string | number)[] = [ip];
    
    // 合并省市信息到loginIpContent字段
    if (province || city) {
      let location = '';
      if (province && city) {
        // 如果省市相同（如北京市北京市），只显示一个
        if (province === city) {
          location = province;
        } else {
          location = `${province}${city}`;
        }
      } else if (province) {
        location = province;
      } else if (city) {
        location = city;
      }
      
      if (location) {
        updateFields.push('loginIpContent = ?');
        updateValues.push(location);
      }
    }
    
    updateFields.push('location_updated_at = CURRENT_TIMESTAMP');
    
    const query = `UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`;
    updateValues.push(userId);
    
    await pool.execute(query, updateValues);
    console.log(`✅ 用户 ${userId} 登录信息已更新 - IP: ${ip}${province || city ? ', 位置: ' + (province && city ? (province === city ? province : `${province}${city}`) : (province || city)) : ''}`);
  } catch (error) {
    console.error('更新用户登录信息失败:', error);
    // 不抛出错误，避免影响主要功能
  }
}

// 高德地图API配置
const AMAP_KEY = 'acd0394167a9ba260e61cea8bc6cedc0';
const AMAP_IP_API = 'https://restapi.amap.com/v3/ip';

// 检查是否为内网IP
function isPrivateIP(ip: string): boolean {
  const privateRanges = [
    /^10\./,                    // 10.0.0.0/8
    /^172\.(1[6-9]|2[0-9]|3[0-1])\./, // 172.16.0.0/12
    /^192\.168\./,              // 192.168.0.0/16
    /^127\./,                   // 127.0.0.0/8 (localhost)
    /^169\.254\./               // 169.254.0.0/16 (link-local)
  ];
  
  return privateRanges.some(range => range.test(ip));
}

// 调用高德地图IP定位API
async function getLocationFromAmap(ip: string): Promise<AmapIpResponse> {
  try {
    console.log(`🌍 正在调用高德地图API定位IP: ${ip}`);
    
    // 检查是否为内网IP
    if (isPrivateIP(ip)) {
      console.log(`⚠️ 检测到内网IP: ${ip}，高德地图API可能无法提供定位信息`);
    }
    
    const response = await axios.get(`${AMAP_IP_API}?ip=${ip}&output=json&key=${AMAP_KEY}`, {
      timeout: 5000,
      headers: {
        'User-Agent': 'xlCig-LocationService/1.0'
      }
    });
    
    console.log('🔍 高德地图API完整响应:', JSON.stringify(response.data, null, 2));
    
    // 详细的错误处理
    if (response.data.status !== '1') {
      const errorMessages: Record<string, string> = {
        '10001': 'key不正确或过期',
        '10002': '没有权限使用相应的服务或者请求接口的路径拼写错误',
        '10003': '访问已超出日访问量',
        '10004': '单位时间内访问过于频繁',
        '10005': 'IP白名单出错，发送请求的服务器IP不在IP白名单内',
        '10006': '绑定域名无效',
        '10007': '数字签名未通过验证',
        '10008': 'MD5安全码未通过验证',
        '10009': '请求key与绑定平台不符',
        '10010': 'IP访问超限',
        '10011': '服务不支持https请求',
        '10012': '权限不足，服务请求被拒绝',
        '10013': 'Key被删除',
        '20000': '请求参数非法',
        '20001': '缺少必填参数',
        '20002': '请求协议非法',
        '20003': '其他未知错误'
      };
      
      const errorMessage = errorMessages[response.data.infocode as string] || response.data.info;
      console.error(`❌ 高德地图API错误 [${response.data.infocode}]: ${errorMessage}`);
      
      // 特殊处理内网IP的情况
      if (isPrivateIP(ip)) {
        console.log(`💡 建议：内网IP ${ip} 无法通过公网定位服务获取地理位置信息`);
      }
    }
    
    return response.data;
  } catch (error) {
    console.error('❌ 调用高德地图API失败:', error);
    throw error;
  }
}
export { getLocationFromAmap };

// 保存IP定位信息到数据库
async function saveIpLocation(locationData: IpLocationData): Promise<void> {
  try {
    console.log('🔄 准备保存IP定位数据到数据库...');
    console.log('📊 原始定位数据:', JSON.stringify(locationData, null, 2));
    
    // 构建安全的数据
    const safeData = {
      ip: locationData.ip || '',
      province: locationData.province || null,
      city: locationData.city || null,
      adcode: locationData.adcode || null,
      rectangle: locationData.rectangle || null,
      response_time: locationData.response_time || new Date()
    };
    
    console.log('🔒 安全处理后的数据:', JSON.stringify(safeData, null, 2));
    
    const query = `
      INSERT INTO ip_addresses (ip, province, city, adcode, rectangle, response_time)
      VALUES (?, ?, ?, ?, ?, ?)
      ON DUPLICATE KEY UPDATE
        province = VALUES(province),
        city = VALUES(city),
        adcode = VALUES(adcode),
        rectangle = VALUES(rectangle),
        response_time = VALUES(response_time)
    `;
    
    const values = [
      safeData.ip,
      safeData.province,
      safeData.city,
      safeData.adcode,
      safeData.rectangle,
      safeData.response_time
    ];
    
    console.log('💾 SQL查询:', query);
    console.log('💾 参数值:', values);
    
    await pool.query(query, values);
    console.log('✅ IP定位数据保存成功');
  } catch (error) {
    console.error('❌ 保存IP定位信息到数据库失败:', error);
    console.error('❌ 错误详情:', error instanceof Error ? error.message : '未知错误');
    throw error;
  }
}

router.get('/', async (ctx) => {
  try {
    // 获取用户真实公网IP的策略
    let publicIP: string;
    let ipSource: string;
    
    // 1. 首先尝试从HTTP头获取用户真实IP
    const clientIP = getClientIP(ctx);
    console.log(`📍 从客户端获取的IP: ${clientIP}`);
    
    // 2. 如果获取到的是公网IP，直接使用
    if (!isPrivateIP(clientIP)) {
      publicIP = clientIP;
      ipSource = 'client_public_ip';
      console.log(`✅ 使用客户端公网IP: ${publicIP}`);
    } else {
      // 3. 如果是内网IP，使用外部API获取真实公网IP
      console.log(`⚠️ 客户端IP是内网IP: ${clientIP}，使用外部API获取公网IP`);
    try {
      publicIP = await getRealPublicIP();
        ipSource = 'external_api';
        console.log(`✅ 通过外部API获取公网IP: ${publicIP}`);
      } catch (error) {
        console.error('❌ 获取公网IP失败，使用客户端IP:', error);
        publicIP = clientIP;
        ipSource = 'client_private_ip';
      }
    }
    
    // 检查用户是否已登录
    const user = checkUserAuth(ctx);
    let isLoggedIn = false;
    let userId = null;
    
    if (user && typeof user === 'object' && 'id' in user) {
      isLoggedIn = true;
      userId = user.id;
      console.log(`🔐 检测到已登录用户: ${userId}, 使用IP: ${publicIP} (来源: ${ipSource})`);
    }
    
    // 首先从数据库查询是否已有该IP的定位信息
    const [existingResult] = await pool.query(
      'SELECT * FROM ip_addresses WHERE ip = ? ORDER BY response_time DESC LIMIT 1',
      [publicIP]
    ) as [RowDataPacket[], any];
    
    let locationData: any = null;
    let useCache = false;
    
    if (existingResult.length > 0) {
      // 检查数据是否过期（例如：超过24小时则重新获取）
      const lastUpdate = new Date(existingResult[0].response_time);
      const now = new Date();
      const hoursDiff = (now.getTime() - lastUpdate.getTime()) / (1000 * 60 * 60);
      
      if (hoursDiff < 24) {
        // 使用数据库中的缓存数据
        locationData = existingResult[0];
        useCache = true;
        console.log('📦 使用缓存的定位数据');
      }
    }
    
    // 如果没有缓存数据或数据过期，则调用高德API
    if (!locationData) {
      try {
        const amapResponse = await getLocationFromAmap(publicIP);
        
        if (amapResponse.status === '1') {
          // API调用成功
          console.log('✅ 高德地图API调用成功，解析数据...');
          console.log('📊 高德API返回的原始数据:', {
            province: amapResponse.province,
            city: amapResponse.city,
            adcode: amapResponse.adcode,
            rectangle: amapResponse.rectangle
          });
          
          // 检查是否有有效的地理位置数据
          const hasValidLocation = amapResponse.province || amapResponse.city || amapResponse.adcode;
          
          if (hasValidLocation) {
            const newLocationData: IpLocationData = {
              ip: publicIP,
              province: amapResponse.province && typeof amapResponse.province === 'string' && amapResponse.province.trim() !== '' ? amapResponse.province : undefined,
              city: amapResponse.city && typeof amapResponse.city === 'string' && amapResponse.city.trim() !== '' ? amapResponse.city : undefined,
              adcode: amapResponse.adcode && typeof amapResponse.adcode === 'string' && amapResponse.adcode.trim() !== '' ? amapResponse.adcode : undefined,
              rectangle: amapResponse.rectangle && typeof amapResponse.rectangle === 'string' && amapResponse.rectangle.trim() !== '' ? amapResponse.rectangle : undefined,
              response_time: new Date()
            };
            
            console.log('📍 解析的定位数据:', JSON.stringify(newLocationData, null, 2));
            
            // 保存到数据库
            await saveIpLocation(newLocationData);
            locationData = newLocationData;
          } else {
            // API成功但没有地理位置数据（通常是内网IP的情况）
            console.log('⚠️ 高德地图API成功返回，但没有地理位置数据');
            locationData = {
              ip: publicIP,
              error: isPrivateIP(publicIP) ? '内网IP无法定位' : '该IP无法获取地理位置',
              error_code: 'NO_LOCATION_DATA'
            };
          }
        } else {
          // API返回错误
          console.error('高德地图API返回错误:', amapResponse);
          locationData = {
            ip: publicIP,
            error: amapResponse.info,
            error_code: amapResponse.infocode
          };
        }
      } catch (apiError) {
        console.error('调用高德地图API异常:', apiError);
        locationData = {
          ip: publicIP,
          error: '无法获取定位信息',
          error_details: apiError instanceof Error ? apiError.message : '未知错误'
        };
      }
    }
    
    // 如果用户已登录且成功获取到定位信息，更新用户的登录IP和定位信息
    if (isLoggedIn && userId && locationData && !locationData.error) {
      await updateUserLocationInfo(
        userId, 
        publicIP, 
        locationData.province, 
        locationData.city
      );
    }
    
    ctx.body = {
      success: true,
      data: {
        ip: publicIP,
        location: locationData,
        cached: useCache,
        user: isLoggedIn ? {
          id: userId,
          locationUpdated: !locationData.error
        } : null,
        ipSource: ipSource,
        ipType: isPrivateIP(publicIP) ? 'private' : 'public',
        debug: {
          clientIP: clientIP,
          isClientPrivate: isPrivateIP(clientIP),
          method: ipSource,
          headers: {
            'x-forwarded-for': ctx.request.headers['x-forwarded-for'],
            'x-real-ip': ctx.request.headers['x-real-ip']
          }
        }
      }
    } as ApiResponse;
    
  } catch (error) {
    console.error('IP定位接口错误:', error);
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: '服务器内部错误',
      data: null
    } as ApiResponse;
  }
});

// IP获取测试接口
router.get('/test-ip', async (ctx) => {
  try {
    const clientIP = getClientIP(ctx);
    const isPrivate = isPrivateIP(clientIP);
    
    let publicIP: string;
    let method: string;
    
    if (!isPrivate) {
      publicIP = clientIP;
      method = 'client_public_ip';
    } else {
      try {
        publicIP = await getRealPublicIP();
        method = 'external_api';
      } catch (error) {
        publicIP = clientIP;
        method = 'fallback_to_client';
      }
    }
    
    ctx.body = {
      success: true,
      data: {
        clientIP: clientIP,
        isClientPrivate: isPrivate,
        finalIP: publicIP,
        method: method,
        headers: {
          'x-forwarded-for': ctx.request.headers['x-forwarded-for'],
          'x-real-ip': ctx.request.headers['x-real-ip'],
          'remote-addr': ctx.request.ip
        }
      }
    } as ApiResponse;
  } catch (error) {
    console.error('IP测试接口错误:', error);
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: 'IP测试失败',
      data: null
    } as ApiResponse;
  }
});

// 调试接口 - 可以指定IP进行测试
router.get('/debug/:ip?', async (ctx) => {
  try {
    let testIp: string;
    
    if (ctx.params.ip) {
      testIp = ctx.params.ip;
      console.log(`🔍 调试模式 - 使用指定IP: ${testIp}`);
    } else {
      // 如果没有指定IP，获取真实公网IP
      try {
        testIp = await getRealPublicIP();
        console.log(`🔍 调试模式 - 获取到的真实公网IP: ${testIp}`);
      } catch (error) {
        testIp = getClientIP(ctx);
        console.log(`🔍 调试模式 - 获取公网IP失败，使用客户端IP: ${testIp}`);
      }
    }
    
    // 检查是否为内网IP
    const isPrivate = isPrivateIP(testIp);
    console.log(`📊 IP类型: ${isPrivate ? '内网IP' : '公网IP'}`);
    
    // 调用高德地图API
    const amapResponse = await getLocationFromAmap(testIp);
    
    ctx.body = {
      success: true,
      data: {
        testIp,
        isPrivateIP: isPrivate,
        amapResponse,
        debug: {
          message: '这是调试接口，显示高德地图API的原始响应',
          usage: '访问 /api/amap/ip/debug 测试真实公网IP，或 /api/amap/ip/debug/8.8.8.8 测试指定IP',
          ipSource: ctx.params.ip ? 'manual' : 'ipinfo.io'
        }
      }
    } as ApiResponse;
    
  } catch (error) {
    console.error('调试接口错误:', error);
    ctx.status = 500;
    ctx.body = {
      success: false,
      message: '调试接口错误',
      data: {
        error: error instanceof Error ? error.message : '未知错误'
      }
    } as ApiResponse;
  }
});

export default router;

